package netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

@Slf4j
public class NettyHttpCase {
    private static final int PORT = 8080;

    @Test
    public void httpServer() throws InterruptedException {
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(4);
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        // 注意 
        try {
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    // .handler() 是给 bossGroup 添加 处理器
                    .childHandler(new HttpServerChannelInitializer());//给 workerGroup 添加 处理器 
            log.error("服务器 准备完成");
            ChannelFuture cf = serverBootstrap.bind(PORT).sync();

            // 对关闭通道进行监听
            cf.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }


    private static class HttpServerChannelInitializer extends ChannelInitializer<SocketChannel> {


        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            log.error("客户端 的 SocketChannel对象的hashCode:{}", ch.hashCode());

            ChannelPipeline pipeline = ch.pipeline();
            // Http 编解嘛器
            pipeline.addLast("MyHttpServerCodec", new HttpServerCodec());
            // 给自己NettyServerHandle
            pipeline.addLast(new HttpServerHandle());
        }
    }

    /**
     * HttpObject：客户端和服务器端相互通讯的数据被封装成 HttpObject
     */
    private static class HttpServerHandle extends SimpleChannelInboundHandler<HttpObject> {

        /**读取客户端数据
         * @param ctx ctx
         * @param msg
         * @throws Exception
         */
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
            
            log.error("msg 类型：{},客户端地址：{}",msg.getClass(),ctx.channel().remoteAddress());
            // 回复信息给浏览器-http协议
            ByteBuf content = Unpooled.copiedBuffer("hello,我是服务器", CharsetUtil.UTF_8);
            HttpRequest request = (HttpRequest) msg;
            String uri = request.getUri();
            System.out.println(uri);
            // 构造一个http response
            DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
            
            // 返回
            ctx.writeAndFlush(response);
        }
    }

}
